package com.paradox.aggregation.gateway.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.Properties;
import java.util.concurrent.Executor;

@Slf4j
public class DynamicRouteInitializer implements ApplicationEventPublisherAware{

    private DynamicRouteSourceProperties dynamicRouteSourceProperties;
    private Properties routeSourceProperties;
    private RouteDefinitionRepository routeDefinitionRepository;

    private ApplicationEventPublisher publisher;

    @Autowired
    public DynamicRouteInitializer(DynamicRouteSourceProperties dynamicRouteSourceProperties, RouteDefinitionRepository routeDefinitionRepository){
        this.dynamicRouteSourceProperties=dynamicRouteSourceProperties;
        this.routeDefinitionRepository=routeDefinitionRepository;
        routeSourceProperties=this.dynamicRouteSourceProperties.build();
    }

    @PostConstruct
    private void init(){
        log.info("Initializing dynamicRoutes config...");
        try {
            ConfigService configService=NacosFactory.createConfigService(routeSourceProperties);
            String content=configService.getConfigAndSignListener(routeSourceProperties.getProperty("dataId"),
                    routeSourceProperties.getProperty("groupId"), 3000L, new Listener() {
                        @Override
                        public Executor getExecutor() {
                            return null;
                        }

                        @Override
                        public void receiveConfigInfo(String configInfo) {
                            refreshConfig(configInfo);
                        }
                    });
            refreshConfig(content);
        }catch (NacosException exception){
            log.error("Failed to load dynamicRoutes!");
        }
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher=applicationEventPublisher;
    }

    private void refreshConfig(String content){
        log.info("Approaching dynamicRoutes config:{}",content);
        JSON.parseArray(content, RouteDefinition.class).forEach(rd -> {
            DynamicRouteInitializer.this.routeDefinitionRepository.save(Mono.just(rd)).subscribe();
            publisher.publishEvent(new RefreshRoutesEvent(this));
        });
    }
}
